package controller;

import common.Message;
import common.MessageType;
import dao.UserDao;
import entity.User;
import service.UserService;
import service.ServerThread;
import tools.ThreadManage;
import view.ServerView;

import java.io.Closeable;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class ServerController implements Runnable {

    private ServerSocket server;
    private Socket client;
    private ObjectInputStream input;
    private ObjectOutputStream output;
    private volatile boolean isRunning;

    public ServerController() {
        isRunning = true;
        new Thread(this).start();
    }

    @Override
    public void run() {
        try {
            // 设置服务器套接字 ServerSocket(int port)创建绑定到指定端口的服务器套接字
            server = new ServerSocket(9999);
            while (isRunning) {
                // 调用accept()方法开始监听，等待客户端的连接
                client = server.accept();
                ServerView.printLog("客户端连接：" + client.getInetAddress());
                input = new ObjectInputStream(client.getInputStream());
                output = new ObjectOutputStream(client.getOutputStream());

                // 等待获取用户信息
                Message msg = (Message) input.readObject();
                Message res = new Message();
                switch (msg.getType()) {
                    case USER_LOGIN:
                        User u = (User) msg.getContent();
                        // 判断是否已经登录
                        if (ThreadManage.getThread(u.getQq()) == null) {// 用户未登录
                            User loginUser = new UserService().login(u.getQq(), u.getPwd());
                            if (loginUser != null) {
                                // 登录成功为该用户创建通信线程
                                ServerThread serverThread = new ServerThread(client);
                                serverThread.setUser(loginUser);
                                serverThread.start();
                                ThreadManage.addThread(loginUser.getQq(), serverThread);
                                res.setType(MessageType.USER_LOGIN);
                                res.setContent(loginUser);
                                ServerView.showUserList();// 更新用户在线状态
                                output.writeObject(res);// 将结果返回给客户端
                            } else {
                                res.setType(MessageType.INFO_ERROR);// qq或者密码错误
                                output.writeObject(res);// 将结果返回给客户端
                            }
                        } else {
                            res.setType(MessageType.SIGNED_IN);// 用户已登录
                            output.writeObject(res);// 将结果返回给客户端
                        }
                        break;
                    case REGISTER:
                        User ru = (User) msg.getContent();
                        User register = new UserService().register(ru);
                        Message message = new Message(MessageType.REGISTER);
                        message.setContent(register);
                        output.writeObject(message);// 将结果返回给客户端
                        break;
                    case CHANGE_PWD:
                        User user = (User) msg.getContent();
                        Boolean aBoolean = new UserService().changePassword(user.getQq(), user.getPwd());
                        Message message1 = new Message(MessageType.REGISTER);
                        message1.setContent(aBoolean);
                        output.writeObject(message1);// 将结果返回给客户端
                        break;
                    case ADD_FRIEND:
                        int[] content = (int[]) msg.getContent();
                        Boolean result = new UserService().addFriend(content[0], content[1]);
                        Message message2 = new Message(MessageType.ADD_FRIEND);
                        message2.setContent(result);
                        output.writeObject(message2);
                        break;
                }
            }
        } catch (IOException | ClassNotFoundException e) {
            myStop();
            e.printStackTrace();
        }
    }

    /**
     * 结束线程运行
     */
    public void myStop() {
        isRunning = false;
        close(server, client, input, output);
    }

    /**
     * 用于关闭多个io流
     *
     * @param ios
     */
    private void close(Closeable... ios) {//可变长参数
        for (Closeable io : ios) {
            try {
                if (io != null) {
                    io.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
